/*******************************************************************************
 * Copyright (c) 2007 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.extensionpoints.transformation.definition;

import java.util.Map;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.debug.core.ILaunchConfiguration;

import com.cea.papyrus.extensionpoints.transformation.Activator;
import com.cea.papyrus.extensionpoints.transformation.launch.LaunchConfigurationIds;

/**
 * Basic implementation for the transformation context
 */
public class TransformationContext implements ITransformationContext {

	/** private attribute that stores the source object */
	private  Object source;
	
	/** private attribute that stores the container */
	private IContainer container;

	/** private attribute that stores the log file path */
	private  String log;
	
	/** private attribute that stores the transformation informations */
	private Transformation transformation;

	/** private attribute that stores the properties */
	private Map<Object, String> properties;
	
	/** private attribute that stores the synchronized info */
	private boolean synch;

	/** private attribute that stores the launch configuration */
	private ILaunchConfiguration configuration;
	
	/**
	 * Constructor retrieve any info of the context using current launch
	 * configuration
	 * @param configuration
	 */
	public TransformationContext(ILaunchConfiguration configuration) {
		
		this.configuration = configuration;

		try {		
			// Get transformation attributes
			this.log = configuration.getAttribute(LaunchConfigurationIds.LOG_ATTRIBUTE_ID, (String) null);
			this.properties = configuration.getAttribute(LaunchConfigurationIds.PROPERTY_MAP_ID, (Map<Object, String>) null);
			
			// Retrieve the transformation
			this.transformation = getTransformation(configuration);

			// Initialize path and containers for transformation
			String containerPath = configuration.getAttribute(LaunchConfigurationIds.CONTAINER_ATTRIBUTE_ID, (String) null);
			if (containerPath != null) {
				IPath containerIPath = new Path(containerPath); 
				container = (IContainer) ResourcesPlugin.getWorkspace().getRoot().findMember(containerIPath);
			}

			// Initialize path and source model for transformation	
			String sourcePath = configuration.getAttribute(LaunchConfigurationIds.MODEL_ATTRIBUTE_ID, (String) null);
			if (sourcePath != null) {
				IPath sourceModelIPath = new Path(sourcePath); 
				source = ResourcesPlugin.getWorkspace().getRoot().findMember(sourceModelIPath);
			}
			
			// Initialize Synch boolean
			String synchValue = configuration.getAttribute(LaunchConfigurationIds.SYNC_BOOL,(String) null);
			if (synchValue != null) {
				synch = new Boolean(synchValue).booleanValue();
			}			
		} catch (CoreException e) {
			Activator.log(e);
		}
	}

	/*
	 * (non-Javadoc)
	 * @see com.cea.papyrus.extensionpoints.transformation.definition.ITransformationContext#getSource()
	 */
	public Object getSource() {
		return source;
	}

	/*
	 * (non-Javadoc)
	 * @see com.cea.papyrus.extensionpoints.transformation.definition.ITransformationContext#getContainer()
	 */
	public IContainer getContainer() {
		return container;
	}

	/*
	 * (non-Javadoc)
	 * @see com.cea.papyrus.extensionpoints.transformation.definition.ITransformationContext#getLog()
	 */
	public String getLog() {
		return log;
	}

	/*
	 * (non-Javadoc)
	 * @see com.cea.papyrus.extensionpoints.transformation.definition.ITransformationContext#getTransformation()
	 */
	public Transformation getTransformation() {
		return transformation;
	}

	/*
	 * (non-Javadoc)
	 * @see com.cea.papyrus.extensionpoints.transformation.definition.ITransformationContext#getConfiguration()
	 */
	public ILaunchConfiguration getConfiguration() {
		return configuration;
	}

	/*
	 * (non-Javadoc)
	 * @see com.cea.papyrus.extensionpoints.transformation.definition.ITransformationContext#isSynchronized()
	 */
	public boolean isSynchronized() {
		return synch;
	}
	
	/*
	 * (non-Javadoc)
	 * @see com.cea.papyrus.extensionpoints.transformation.definition.ITransformationContext#getProperties()
	 */
	public Map<Object, String> getProperties() {
		return properties;
	}
	
	/*
	 * (non-Javadoc)
	 * @see com.cea.papyrus.extensionpoints.transformation.definition.ITransformationContext#getProject()
	 */
	public IProject getProject() {
		return container.getProject();
	}
	
	/**
	 * Retrieves a module by its id.
	 * @param configuration
	 * @return the module
	 * @throws CoreException
	 */
	private static Transformation getTransformation(ILaunchConfiguration configuration)
	throws CoreException {
		String moduleId = configuration.getAttribute(LaunchConfigurationIds.MODULE_ATTRIBUTE_ID, (String) null);
		IExtensionRegistry registry = Platform.getExtensionRegistry();
		IExtensionPoint extensionPoint = registry.getExtensionPoint(TransformationExtIds.TRANSFORMATION_EXTENSION_ID);
		if (extensionPoint == null) {
			Activator.log("unable to resolve extension-point: "+ TransformationExtIds.TRANSFORMATION_EXTENSION_ID.toString());
		} else {
			IExtension[] extensions = extensionPoint.getExtensions();
			for (int i = 0; i < extensions.length; i++) {
				IExtension extension = extensions[i];
				IConfigurationElement[] members = extension.getConfigurationElements();
				for (int j = 0; j < members.length; j++) {
					
					// Parse configuration elements for this extension (Transformations or Groups)
					IConfigurationElement current = members[j];
					if (current.getName().equals(TransformationExtIds.TAG_TRANSFORMATION)) {
						// current is a transformation
						Transformation transformation = new Transformation(current);
						if (transformation.getId().equals(moduleId)) {
							return transformation;
						}
					} else if (current.getName().equals(GroupExtIds.TAG_GROUP)) {
						// If current is a group of transformation, parse each
						Transformation[] ownedTransfos = (new Group(current)).getTransformations();
						for (int k = 0; k < ownedTransfos.length; k++) {
							if (ownedTransfos[k].getId().equals(moduleId)) {
								return ownedTransfos[k];
							}
						}
					}
				}
			}
		}
		return null;
	}
	
}
